package fr.blogger.web.bean.securite.spring;

import org.springframework.dao.DataAccessException;
import org.springframework.security.authentication.AuthenticationServiceException;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.authentication.dao.AbstractUserDetailsAuthenticationProvider;
import org.springframework.security.authentication.encoding.ShaPasswordEncoder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;

import fr.blogger.ejb.facade.UtilisateurFacade;
import fr.blogger.ejb.model.Utilisateur;
import fr.blogger.ejb.outils.UtilsAuthentication;
import fr.blogger.ejb.outils.UtilsEJB;

public class CustomAuthenticationProvider extends AbstractUserDetailsAuthenticationProvider {

	private ShaPasswordEncoder passwordEncoder;

	private UserDetailsService userDetailsService;

	private boolean includeDetailsObject = true;

	private Integer nombreMaxEchecConnexion;

	public CustomAuthenticationProvider() {
	}

	@Override
	protected void additionalAuthenticationChecks(UserDetails userDetails, UsernamePasswordAuthenticationToken authentication) {
		Utilisateur user = (Utilisateur) userDetails;

		if (authentication.getCredentials() == null) {
			throw new BadCredentialsException("Veuillez renseigner le nom d'utilisateur et le mot de passe avant de vous authentifier");
		}
		String presentedPassword = authentication.getCredentials().toString();
		if (!user.getPassword().equals(UtilsAuthentication.chiffrerMotdepasse(presentedPassword, user.getDateCreation()))) {
			int nombreEchecConnexion = user.getNombreEchecConnexion() + 1;
			if (nombreEchecConnexion >= nombreMaxEchecConnexion) {
				throw new AuthenticationServiceException("Trop de tentative en echec de connexion. Veuillez contacter l'administrateur pour déverouiller votre compte.");
			}
			user = UtilsEJB.getService(UtilisateurFacade.class).modificationNombreEchecConnexion(user, nombreEchecConnexion);
			throw new BadCredentialsException("Nom d'utilisateur ou mot de passe incorrect");
		}
	}

	@Override
	protected UserDetails retrieveUser(String username, UsernamePasswordAuthenticationToken pAuthentication) {
		Utilisateur user;
		if ((username == null) || username.isEmpty()) {
			throw new AuthenticationServiceException("Veuillez correctement renseigner le nom d'utilisateur");
		}
		try {
			user = UtilsEJB.getService(UtilisateurFacade.class).getUtilisateurByUsername(username);
			if (user == null) {
				throw new BadCredentialsException("Nom d'utilisateur ou mot de passe incorrect");
			}
		} catch (DataAccessException repositoryProblem) {
			throw new AuthenticationServiceException("Problème d'accès aux données");
		}
		return user;
	}

	public ShaPasswordEncoder getPasswordEncoder() {
		return passwordEncoder;
	}

	public void setPasswordEncoder(ShaPasswordEncoder passwordEncoder) {
		this.passwordEncoder = passwordEncoder;
	}

	public UserDetailsService getUserDetailsService() {
		return this.userDetailsService;
	}

	public void setUserDetailsService(UserDetailsService userDetailsService) {
		this.userDetailsService = userDetailsService;
	}

	public boolean isIncludeDetailsObject() {
		return this.includeDetailsObject;
	}

	public void setIncludeDetailsObject(boolean includeDetailsObject) {
		this.includeDetailsObject = includeDetailsObject;
	}

	public Integer getNombreMaxEchecConnexion() {
		return nombreMaxEchecConnexion;
	}

	public void setNombreMaxEchecConnexion(Integer pNombreMaxEchecConnexion) {
		nombreMaxEchecConnexion = pNombreMaxEchecConnexion;
	}

}
